package com.didi.gulimall.coupon.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.didi.gulimall.common.constant.BizCodeEnume;
import com.didi.gulimall.common.constant.CartConstant;
import com.didi.gulimall.common.constant.CouponConstant;
import com.didi.gulimall.common.exception.DuplicateFieldsException;
import com.didi.gulimall.common.utils.R;
import com.didi.gulimall.common.vo.OrderItemVo;
import com.didi.gulimall.common.vo.OrderVo;
import com.didi.gulimall.coupon.entity.MemberPriceEntity;
import com.didi.gulimall.coupon.entity.SkuFullReductionEntity;
import com.didi.gulimall.coupon.entity.SkuLadderEntity;
import com.didi.gulimall.coupon.service.*;
import com.didi.gulimall.coupon.vo.CalculateDiscountVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author 10626
 * @Create 2021/7/7 16:00
 */
@Service
@Slf4j
public class OrderDiscountServiceImpl implements OrderDiscountService {
    @Autowired
    private SkuFullReductionService skuFullReductionService;

    @Autowired
    private SpuBoundsService spuBoundsService;

    @Autowired
    private SkuLadderService skuLadderService;

    @Autowired
    private MemberPriceService memberPriceService;

    private ThreadLocal<CalculateDiscountVo> local = new ThreadLocal<>();

    @Override
    public R queryOrderDistant(Long levelId, List<OrderItemVo> cartItems) {
        List<OrderItemVo> orderItemVos = new ArrayList<>();
        cartItems = cartItems.stream().filter(OrderItemVo::getCheck).collect(Collectors.toList());
        OrderVo orderVo = new OrderVo();

        // 0位置促销价 1位置 会员满减  2位置 满减 选中1 不选中0
        if (CollectionUtils.isNotEmpty(cartItems)) {
            Integer count = 0;
            BigDecimal totalAmount = BigDecimal.ZERO;
            CalculateDiscountVo calculateDiscountVo = new CalculateDiscountVo();
            local.set(calculateDiscountVo);
            BigDecimal totalFullDiscount = calculateDiscountVo.getTotalFullDiscount();
            BigDecimal totalMemberTieredPrice = calculateDiscountVo.getTotalMemberTieredPrice();
            BigDecimal totalPromotionAmount = calculateDiscountVo.getTotalPromotionAmount();
            for (OrderItemVo orderItem : cartItems) {
                Integer[] work = {0, 0, 0};
                orderItem.setWork(work);
                // 获取积分优惠
                spuBoundsService.getBonusPoints(orderItem);
                BigDecimal multiply = orderItem.getPrice().multiply(new BigDecimal(orderItem.getCount()));
                orderItem.setTotalPrice(multiply);
                // 会员
                memberPrice(levelId, orderItem);
                // 满减
                fullReduction(orderItem);
                // 促销
                promotion(orderItem);
                // 计算选中那些
                calculateDiscount(orderItem);
                totalAmount = totalAmount.add(orderItem.getTotalPrice());
                count = count += orderItem.getCount();
                orderItemVos.add(orderItem);
            }
            CalculateDiscountVo calculateDiscountVo1 = local.get();
            totalFullDiscount = calculateDiscountVo.getTotalFullDiscount();
            totalMemberTieredPrice = calculateDiscountVo.getTotalMemberTieredPrice();
            totalPromotionAmount = calculateDiscountVo.getTotalPromotionAmount();
            orderVo.setTotalAmount(totalAmount);
            BigDecimal subtract = totalAmount.subtract(totalFullDiscount).subtract(totalMemberTieredPrice).subtract(totalPromotionAmount);
            orderVo.setTotalPricePayable(subtract);
            orderVo.setCountNum(count);
            orderVo.setCountType(cartItems.size());
            orderVo.setTotalFullDiscount(totalFullDiscount);
            orderVo.setTotalPromotionAmount(totalPromotionAmount);
            orderVo.setTotalMemberTieredPrice(totalMemberTieredPrice);
            orderVo.setItems(orderItemVos);
        }
        log.info("优惠信息:{}", JSON.toJSONString(orderVo));
        return R.ok().put("data", orderVo);
    }

    @Override
    public R checkOrderDistant(Long levelId, List<OrderItemVo> cartItems) {
        BigDecimal totalAmount = BigDecimal.ZERO;
        BigDecimal totalFullDiscount = BigDecimal.ZERO;
        BigDecimal totalMemberTieredPrice = BigDecimal.ZERO;
        BigDecimal totalPromotionAmount = BigDecimal.ZERO;
        OrderVo orderVo = new OrderVo();
        for (OrderItemVo orderItem : cartItems) {
            Integer[] work = orderItem.getWork();
            Integer work1 = work[0];
            Integer work2 = work[0];
            Integer work3 = work[0];
            BigDecimal price = orderItem.getPrice().multiply(new BigDecimal(orderItem.getCount()));
            orderItem.setTotalPrice(price);
            if (work1 == 1) {
                SkuLadderEntity one = skuLadderService.getOne(new QueryWrapper<SkuLadderEntity>().eq("sku_id", orderItem.getSkuId()));
                if (one == null || one.getAddOther() != 1 || orderItem.getCount() < one.getFullCount()) {
                    throw new DuplicateFieldsException(BizCodeEnume.CHECK_OFFER_ERROR.getMsg());
                }
                orderItem.setPromotionAmount(price.multiply(one.getDiscount()));
                totalPromotionAmount = totalPromotionAmount.add(price.subtract(price.multiply(one.getDiscount())));
            }
            if (work2 == 1) {
                MemberPriceEntity memberPriceEntity = memberPriceService.getMemberTieredPrice(orderItem.getSkuId(), levelId);
                if (memberPriceEntity == null || (memberPriceEntity.getAddOther() != 1)) {
                    throw new DuplicateFieldsException(BizCodeEnume.CHECK_OFFER_ERROR.getMsg());
                }
                orderItem.setMemberTieredPrice(memberPriceEntity.getMemberPrice());
                BigDecimal multiply = (orderItem.getPrice().subtract(memberPriceEntity.getMemberPrice())).multiply(new BigDecimal(orderItem.getCount()));
                totalMemberTieredPrice = totalMemberTieredPrice.add(multiply);
            }
            if (work3 == 1) {
                SkuFullReductionEntity skuFullReduction = skuFullReductionService.getFullReduction(orderItem.getSkuId());
                if (skuFullReduction == null || skuFullReduction.getAddOther() != 1 || orderItem.getTotalPrice().compareTo(skuFullReduction.getFullPrice()) < 0) {
                    throw new DuplicateFieldsException(BizCodeEnume.CHECK_OFFER_ERROR.getMsg());
                }
                orderItem.setFullDiscount(skuFullReduction.getReducePrice());
                totalFullDiscount = totalFullDiscount.add(skuFullReduction.getReducePrice());
            }
            totalAmount = totalAmount.add(price);
        }
        BigDecimal subtract = totalAmount.subtract(totalFullDiscount).subtract(totalMemberTieredPrice).subtract(totalPromotionAmount);
        orderVo.setTotalPromotionAmount(totalPromotionAmount);
        orderVo.setTotalAmount(totalAmount);
        orderVo.setTotalFullDiscount(totalFullDiscount);
        orderVo.setTotalMemberTieredPrice(totalMemberTieredPrice);
        orderVo.setTotalPricePayable(subtract);
        return R.ok().put("data",orderVo);
    }

    private void promotion(OrderItemVo orderItem) {
        Integer[] work = orderItem.getWork();
        QueryWrapper<SkuLadderEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("sku_id", orderItem.getSkuId());
        SkuLadderEntity one = skuLadderService.getOne(queryWrapper);
        if (one == null) {
            orderItem.setMemberTieredPrice(BigDecimal.ZERO);
            orderItem.setWhetherMemberTieredPrice(true);
            work[0] = 1;
        } else {
            if (orderItem.getCount() >= one.getFullCount()) {
                BigDecimal multiply = orderItem.getTotalPrice().multiply(one.getDiscount());
                orderItem.setPromotionAmount(multiply);
                if (one.getAddOther() == 1) {
                    orderItem.setWhetherPromotionAmount(true);
                    work[0] = 1;
                }
            }
        }
    }

    private void memberPrice(Long levelId, OrderItemVo orderItem) {
        Integer[] work = orderItem.getWork();
        if (!levelId.equals(CartConstant.DEFAULT_LEVEL)) {
            MemberPriceEntity memberPriceEntity = memberPriceService.getMemberTieredPrice(orderItem.getSkuId(), levelId);
            if (memberPriceEntity == null) {
                orderItem.setMemberTieredPrice(BigDecimal.ZERO);
                orderItem.setWhetherMemberTieredPrice(true);
                work[1] = 1;
            } else {
                orderItem.setMemberTieredPrice(memberPriceEntity.getMemberPrice());
                if (memberPriceEntity.getAddOther() == 1) {
                    orderItem.setWhetherMemberTieredPrice(memberPriceEntity.getAddOther() == 1);
                    work[1] = 1;
                }
            }
        }
    }

    private void fullReduction(OrderItemVo orderItem) {
        Integer[] work = orderItem.getWork();
        SkuFullReductionEntity skuFullReduction = skuFullReductionService.getFullReduction(orderItem.getSkuId());
        if (skuFullReduction == null) {
            orderItem.setFullDiscount(BigDecimal.ZERO);
            orderItem.setWhetherDullDiscount(true);
            work[2] = 1;
        } else {
            orderItem.setFullDiscountStr(skuFullReduction.getFullPrice() + "_" + skuFullReduction.getReducePrice());
            if (orderItem.getTotalPrice().compareTo(skuFullReduction.getFullPrice()) > -1) {
                orderItem.setFullDiscount(skuFullReduction.getReducePrice());
                if (skuFullReduction.getAddOther() == 1) {
                    orderItem.setWhetherDullDiscount(skuFullReduction.getAddOther() == 1);
                    work[2] = 1;
                }
            }
        }
    }

    /**
     * // 0位置促销价 1位置 会员满减  2位置 满减 选中1 不选中0
     *
     * @param orderItem
     */
    private void calculateDiscount(OrderItemVo orderItem) {
        Integer[] work = orderItem.getWork();
        CalculateDiscountVo calculateDiscountVo = local.get();
        BigDecimal totalFullDiscount = calculateDiscountVo.getTotalFullDiscount();
        BigDecimal totalMemberTieredPrice = calculateDiscountVo.getTotalMemberTieredPrice();
        BigDecimal totalPromotionAmount = calculateDiscountVo.getTotalPromotionAmount();
        Integer selectedLength = getSelected(work);
        BigDecimal priceAfterDiscount = orderItem.getPromotionAmount();
        BigDecimal promotionAmount = BigDecimal.ZERO;
        if (priceAfterDiscount.compareTo(BigDecimal.ZERO) > 0) {
            promotionAmount = orderItem.getTotalPrice().subtract(priceAfterDiscount);
        }
        BigDecimal memberTieredPrice = (orderItem.getPrice().subtract(orderItem.getMemberTieredPrice())).multiply(new BigDecimal(orderItem.getCount()));
        BigDecimal fullDiscount = orderItem.getFullDiscount();
        if (selectedLength == 3) {
            totalFullDiscount = totalFullDiscount.add(fullDiscount);
            totalMemberTieredPrice = totalMemberTieredPrice.add(memberTieredPrice);
            totalPromotionAmount = totalPromotionAmount.add(promotionAmount);
        } else if (selectedLength <= 1) {
            work = new Integer[]{0, 0, 0};
            if (promotionAmount.compareTo(memberTieredPrice) > 0) {
                if (promotionAmount.compareTo(fullDiscount) > 0) {
                    work[0] = 1;
                    totalPromotionAmount = totalPromotionAmount.add(promotionAmount);
                }
            } else {
                if (memberTieredPrice.compareTo(fullDiscount) > 0) {
                    work[1] = 1;
                    totalMemberTieredPrice = totalMemberTieredPrice.add(memberTieredPrice);
                } else {
                    work[2] = 1;
                    totalFullDiscount = totalFullDiscount.add(fullDiscount);
                }
            }
        } else {
            BigDecimal overlayOffer = BigDecimal.ZERO;
            BigDecimal noOverlayOffer = BigDecimal.ZERO;
            Integer work1 = work[0];
            Integer work2 = work[1];
            Integer work3 = work[2];
            int flagBit = 0;
            String bit = "0";
            // 当不叠加优惠大于叠加优惠时为true
            if (work1 == 0) {
                bit = "1_2";
                noOverlayOffer = noOverlayOffer.add(promotionAmount);
            } else {
                overlayOffer = overlayOffer.add(promotionAmount);
            }
            if (work2 == 0) {
                bit = "0_2";
                flagBit = 1;
                noOverlayOffer = noOverlayOffer.add(memberTieredPrice);
            } else {
                overlayOffer = overlayOffer.add(memberTieredPrice);
            }
            if (work3 == 0) {
                bit = "0_1";
                flagBit = 2;
                noOverlayOffer = noOverlayOffer.add(fullDiscount);
            } else {
                overlayOffer = overlayOffer.add(fullDiscount);
            }
            work = new Integer[]{0, 0, 0};
            // 不叠加大于叠加
            if (noOverlayOffer.compareTo(overlayOffer) > 0) {
                work[flagBit] = 1;
                if (flagBit == 0) {
                    totalPromotionAmount = totalPromotionAmount.add(promotionAmount);
                } else if (flagBit == 1) {
                    totalMemberTieredPrice = totalMemberTieredPrice.add(memberTieredPrice);
                } else {
                    totalFullDiscount = totalFullDiscount.add(fullDiscount);
                }
            } else {
                //不叠加小于于叠加
                String[] split = bit.split("_");
                if (split[0].equals(CouponConstant.PROMOTION_DISCOUNT_LOCATION) || split[1].equals(CouponConstant.PROMOTION_DISCOUNT_LOCATION)) {
                    work[0] = 1;
                    totalPromotionAmount = totalPromotionAmount.add(promotionAmount);
                }
                if (split[0].equals(CouponConstant.MEMBER_DISCOUNT_LOCATION) || split[1].equals(CouponConstant.MEMBER_DISCOUNT_LOCATION)) {
                    work[1] = 1;
                    totalMemberTieredPrice = totalMemberTieredPrice.add(memberTieredPrice);
                }
                if (split[0].equals(CouponConstant.FULL_DISCOUNT_LOCATION) || split[1].equals(CouponConstant.FULL_DISCOUNT_LOCATION)) {
                    work[2] = 1;
                    totalFullDiscount = totalFullDiscount.add(fullDiscount);
                }
            }
        }
        orderItem.setWork(work);
        calculateDiscountVo.setTotalFullDiscount(totalFullDiscount);
        calculateDiscountVo.setTotalMemberTieredPrice(totalMemberTieredPrice);
        calculateDiscountVo.setTotalPromotionAmount(totalPromotionAmount);
        local.set(calculateDiscountVo);
    }

    private Integer getSelected(Integer[] work) {
        int count = 0;
        for (Integer integer : work) {
            if (integer == 1) {
                count++;
            }
        }
        return count;
    }
}
